package org.tigris.atlas.xml.schema.mda.element;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.tigris.atlas.mda.metadata.element.Operation;
import org.tigris.atlas.mda.metadata.element.Parameter;

public class SchemaOperation implements Operation {

	private Operation operation;
	private List decoratedParameterList;
	private String parameterNames;
	private Set namespaces;

	public SchemaOperation(Operation operationToDecorate) {
		if (operationToDecorate == null) {
			throw new IllegalArgumentException("SchemaOperation must be instatiated with a non-null operation!");
		}
		operation = operationToDecorate;
	}

	public String getName() {
		return operation.getName();
	}

	public String getReturnType() {
		return operation.getReturnType();
	}

	public String getLowercaseName() {
		return operation.getLowercaseName();
	}

	public List getParameters() {
		if (decoratedParameterList == null) {
			List operationParameterList = operation.getParameters();
			if ((operationParameterList == null) || (operationParameterList.size() == 0)) {
				decoratedParameterList = Collections.EMPTY_LIST;

			} else {
				Parameter p;
				decoratedParameterList = new ArrayList((int)(operationParameterList.size()));
				Iterator i = operationParameterList.iterator();
				while (i.hasNext()) {
					p = (Parameter)i.next();
					SchemaParameter sp = new SchemaParameter(p);
					decoratedParameterList.add( sp );
				}

			}
		}

		return decoratedParameterList;
	}

	public String getReturnManyType() {
		return operation.getReturnManyType();
	}

	public String getTransactionAttribute() {
		return operation.getTransactionAttribute();
	}

	public String getParameterNames() {
		if (parameterNames == null) {
			StringBuffer buff = new StringBuffer(100);
			for (Iterator i = getParameters().iterator(); i.hasNext();) {
				Parameter param = (Parameter) i.next();
				buff.append(param.getName());
				if (i.hasNext()) {
					buff.append(", ");
				}
			}
			parameterNames = buff.toString();
		}

		return parameterNames;
	}

	private String getType() {
		return getReturnType()==null ? getReturnManyType() : getReturnType();
	}

	public String getViewType() {
		return operation.getViewType();
	}

	/**
	 * Returns whether or not this operation is available to remote clients
	 * @return <tt>Boolean</tt>
	 */
	public Boolean isRemote() {
		String viewType = getViewType();
		return new Boolean((Operation.VIEW_TYPE_BOTH.equals(viewType) || Operation.VIEW_TYPE_REMOTE.equals(viewType)));
	}

	/**
	 * Returns whether or not this operation is available to local clients
	 * @return <tt>Boolean</tt>
	 */
	public Boolean isLocal() {
		String viewType = getViewType();
		return new Boolean((Operation.VIEW_TYPE_BOTH.equals(viewType) || Operation.VIEW_TYPE_LOCAL.equals(viewType)));
	}

	public String getTransmissionMethod() {
		return operation.getTransmissionMethod();
	}

	/**
	 * Returns whether or not this operation is synchronous
	 * @return <tt>Boolean</tt>
	 */
	public Boolean isSynchronous() {
		String transmissionMethod = getTransmissionMethod();
		return new Boolean((Operation.TRANSMISSION_METHOD_SYNC.equals(transmissionMethod)));
	}

	/**
	 * Returns whether or not this operation is asynchronous
	 * @return <tt>Boolean</tt>
	 */
	public Boolean isAsynchronous() {
		String transmissionMethod = getTransmissionMethod();
		return new Boolean((Operation.TRANSMISSION_METHOD_ASYNC.equals(transmissionMethod)));
	}

	//schema-specific generation methods:

	public String getSchemaReturnType() {
		return SchemaElementUtils.getSchemaType(getType());
	}

	public Set getNamespaces() {
		if( namespaces == null ) {
			namespaces = new HashSet();
			Iterator i = getParameters().iterator();
			SchemaParameter sp = null;
			while( i.hasNext() ) {
				sp = (SchemaParameter) i.next();
				SchemaEntity se = sp.getEntity();
				if( se != null ) {
					namespaces.add( new SchemaNamespace(se) );
				}
			}
		}

		return namespaces;
	}

	public String getDocumentation() {
		return operation.getDocumentation();
	}

}
